#pragma once

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>

// #define MySelf 1

const std::string blank_space_sep = " ";
const std::string protocol_sep = "\n";

// data1 op data2 => "len \n data1 op data2"
std::string Encode(std::string &content)
{
    std::string package = std::to_string(content.size());
    package += protocol_sep;
    package += content;
    package += protocol_sep;

    return package;
}

// "len \n data1 op data2" => "data1 op data2"
bool Decode(std::string &package, std::string *content)
{

    size_t pos = package.find(protocol_sep);
    if(pos == std::string::npos) return false;
    std::string len_str = package.substr(0, pos);
    int len = std::stoi(len_str);
    // 检查合法性
    // package = len_str + content_str + 2(2个\n)
    size_t total_len = len_str.size() + len  + 2;
    if(package.size() < total_len) return false;
    *content = package.substr(pos + 1, len);
    // earse 移除报文
    package.erase(0, total_len);
    return true;
}

class Request
{
public:
    Request(int data1, int data2, char op) : m_data1(data1), m_data2(data2), m_op(op)
    {}
    Request(){}
    ~Request() {}

public:
    // 把结构化的数据转化成字符串 struct => string
    bool Serialize(std::string *out)
    {
#ifdef MySelf
        // 构建报文的有效载荷
        std::string str = std::to_string(m_data1);
        str += blank_space_sep;
        str += m_op;
        str += blank_space_sep;
        str += std::to_string(m_data2);
        *out = str;
        return true;
#else
        Json::Value root;
        root["data1"] = m_data1;
        root["data2"] = m_data2;
        root["op"] = m_op;

        // Json::FastWriter w;
        Json::StyledWriter w;
        *out = w.write(root);
        return true;
#endif
    }

    bool Deserialize(const std::string &in) // "data1 op data2"
    {
#ifdef MySelf
        size_t left = in.find(blank_space_sep);
        if(left == std::string::npos)  return false;
        std::string part_data1 = in.substr(0, left);

        size_t right = in.rfind(blank_space_sep);
        if(right == std::string::npos) return false;
        std::string part_data2 = in.substr(right + 1);

        if(left + 2 != right) return false;
        // std::string oper = in.substr(left + 1, right + 1);
        m_op = in[left + 1];
        m_data1 = std::stoi(part_data1);
        m_data2 = std::stoi(part_data2);

        return true;
#else
        Json::Value root;
        Json::Reader r;
        r.parse(in, root);

        m_data1 = root["data1"].asInt();
        m_data2 = root["data2"].asInt();
        m_op = root["op"].asInt();
        return true;
#endif
    }

    void DebugPrint()
    {
        std::cout << "新请求构建完成 " << m_data1 << m_op << m_data2 << "=?" << std::endl;
    }

public:
    int m_data1;
    int m_data2;
    char m_op;
};

class Response
{
public:
    Response(int result, int exitcode) : m_result(result), m_exitcode(exitcode)
    {}

    Response(){}
    ~Response()
    {}

public:
    bool Serialize(std::string *out)
    {
#ifdef  MySelf
        // "result code"
        std::string str = std::to_string(m_result);
        str += blank_space_sep;
        str += std::to_string(m_exitcode);
        *out = str;
        return true;
#else
        Json::Value root;
        root["result"] = m_result;
        root["exitcode"] = m_exitcode;

        // Json::FastWriter w;
        Json::StyledWriter w;
        *out = w.write(root); 
        return true;
#endif
    }

    bool Deserialize(const std::string &in) // "result code"
    {
#ifdef  MySelf
        size_t pos = in.find(blank_space_sep);
        if(pos == std::string::npos)  return false;
        std::string result = in.substr(0, pos);
        std::string exitcode = in.substr(pos + 1);

        m_result = std::stoi(result);
        m_exitcode = std::stoi(exitcode);
        return true;
#else
        Json::Value v;
        Json::Reader r;
        r.parse(in, v);

        m_result = v["result"].asInt();
        m_exitcode = v["exitcode"].asInt();
        return true;
#endif
    }

    void DebugPrint()
    {
        std::cout << "结果响应完成, result: " << m_result << ", exitcode: " <<m_exitcode << std::endl;
    }
public:
    int m_result;
    int m_exitcode; // 错误码 0：可信  非0， 具体是几，表示对应的错误原因
};